package com.we.wfc.common.redisson;

import com.google.gson.Gson;
import com.we.wfc.common.enums.ReturnCode;
import com.we.wfc.common.pojo.ResultPoJo;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;

/**
 * @Description: 防止重复提交的过滤器
 * @Author:Liangzy(Feeling)
 * @Date:Create in 2020/1/7 5:54 下午
 */
@ConditionalOnProperty({"spring.redisson.enable"})
@WebFilter(urlPatterns = "/g/*", filterName = "avoidduplicatesubmissionfilter")
public class AvoidDuplicateSubmissionFilter implements Filter {

    /**
     * Http Method
     */
    private final String POST = "POST";
    private final String PUT = "PUT";
    private final String DELETE = "DELETE";
    private final String PATCH = "PATCH";


    @Override
    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        //防止后续的Filter和Controller获取不到request数据流
        WrappedHttpServletRequest requestWrapper = new WrappedHttpServletRequest((HttpServletRequest) request);
        //针对post请求进行处理
        if (this.POST.equals(requestWrapper.getMethod().toUpperCase()) ||
                this.PUT.equals(requestWrapper.getMethod().toUpperCase()) ||
                this.DELETE.equals(requestWrapper.getMethod().toUpperCase()) ||
                this.PATCH.equals(requestWrapper.getMethod().toUpperCase())) {
            //对请求参数和url以及权限串，进行签名
            String requestMd5Sign = RequestSaltSignUtil.requestMd5Sign(requestWrapper);
            Boolean whetherUnlock = true;
            try {
                //尝试加锁，等待时间为0，超时时间为10秒
                int expireDate = 10;
                if (RedissLockUtil.tryLock(requestMd5Sign, 0, expireDate)) {
                    // 获取到锁放行
                    chain.doFilter(requestWrapper, response);
                } else {
                    //未获取到锁，说明是重复请求，进行拦截
                    ResultPoJo<ReturnCode> poJo = new ResultPoJo<>();
                    poJo.setErrorStatus(ReturnCode.REPEAT_OPERATION);
                    //返回提示信息
                    response.setContentType("application/json; charset=utf-8");
                    response.getWriter().write(new Gson().toJson(poJo));
                    whetherUnlock = false;
                }
            } finally {
                //释放锁
                if (whetherUnlock) {
                    //检查此锁被任何线程锁定，防止其它线程对锁进行释放
                    if (RedissLockUtil.isLocked(requestMd5Sign)) {
                        RedissLockUtil.unlock(requestMd5Sign);
                    }
                }
            }
        } else {
            //get请求，直接放行
            chain.doFilter(requestWrapper, response);
        }
    }
}
